package com.hjm.friend.manage;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.PageHelper;
import com.hjm.common.core.constants.CacheConstants;
import com.hjm.common.core.domain.page.PageDomain;
import com.hjm.redis.service.RedisService;
import com.hjm.friend.domain.message.vo.MessageTextCacheVO;
import com.hjm.friend.mapper.message.MessageTextMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class MessageCacheManager {


    @Autowired
    private MessageTextMapper messageTextMapper;

    @Autowired
    private RedisService redisService;


    public Long getListSize(Long userId) {
        return redisService.getListSize(getUserMsgListKey(userId));
    }


    public void refreshCache(Long userId) {
        List<MessageTextCacheVO> msgTextVOList =messageTextMapper.selectUserMsgList(userId);
        if (CollectionUtils.isEmpty(msgTextVOList)) {
            return;
        }
        // 重置 用户竞赛排名 缓存
        List<Long> textIdList = msgTextVOList.stream().map(MessageTextCacheVO::getTextId).collect(Collectors.toList());
        String userMsgListKey = getUserMsgListKey(userId);
        redisService.rightPushAll(userMsgListKey, textIdList);

        // 重置 竞赛列表缓存
        Map<String, MessageTextCacheVO> msgVOMap = new HashMap<>();
        for (MessageTextCacheVO msgTextVO : msgTextVOList) {
            msgVOMap.put(getMsgDetailKey(msgTextVO.getTextId()), msgTextVO);
        }
        redisService.multiSet(msgVOMap);

    }

    public List<MessageTextCacheVO> getMsgTextVOList(PageDomain pageDto, Long userId) {
        int start = (pageDto.getPageNum() -1) * pageDto.getPageSize();    // 开始下标
        int end = start + pageDto.getPageSize() -1 ;                           // 结束下标
        String userMsgListKey = getUserMsgListKey(userId);
        List<Long> textIdList = redisService.getCacheListByRange(userMsgListKey, start, end, Long.class);
        List<MessageTextCacheVO> msgTextVOList = assembleExamVOList(textIdList);
        if(CollectionUtil.isEmpty(msgTextVOList)){
            // 没有找到数据，说明 redis 中数据 存在问题，需要刷新以下缓存
            msgTextVOList = getMsgTextVOListByDB(pageDto,userId);
            refreshCache(userId);
        }
        return msgTextVOList;
    }



    public void deleteCache(Long userId, Long textId) {

        // 删除用户消息列表缓存
        String userMsgListKey = getUserMsgListKey(userId);
        Long textIdIndex = redisService.indexOfForListValue(userMsgListKey, textId);
        redisService.removeForList(userMsgListKey, textIdIndex);

        // 删除消息详情缓存
        String msgDetailKey = getMsgDetailKey(textId);
        redisService.deleteObject(msgDetailKey);
    }


    public List<MessageTextCacheVO> assembleExamVOList(List<Long> textIdList) {
        if(CollectionUtil.isEmpty(textIdList)){
            // redis 中 无数据
            return null;
        }
        List<String> detailKeyList = new ArrayList<>();
        for(Long textId : textIdList){
            detailKeyList.add(getMsgDetailKey(textId));
        }
        List<MessageTextCacheVO> messageTextVOList = redisService.multiGet(detailKeyList, MessageTextCacheVO.class);
        CollUtil.removeNull(messageTextVOList);
        if(CollectionUtil.isEmpty(messageTextVOList) || messageTextVOList.size()  != textIdList.size()){
            // redis 中 数据 存在问题
            return null;
        }
        return messageTextVOList;
    }

    // 从数据库中获取信息
    public List<MessageTextCacheVO> getMsgTextVOListByDB(PageDomain pageDto, Long userId) {
        PageHelper.startPage(pageDto.getPageNum(),
                pageDto.getPageSize());
        return messageTextMapper.selectUserMsgList(userId);
    }

    private String getUserMsgListKey(Long userId) {
        return CacheConstants.USER_MESSAGE_LIST + userId;
    }

    private String getMsgDetailKey(Long textId) {
        return CacheConstants.MESSAGE_DETAIL+textId;
    }


}
